package cn.chiship.framework.docs.biz.controller;

import cn.chiship.framework.common.annotation.SystemOptionAnnotation;
import cn.chiship.framework.common.enums.BusinessTypeEnum;
import cn.chiship.framework.docs.biz.entity.*;
import cn.chiship.framework.docs.biz.pojo.dto.FileResourcesRenameDto;
import cn.chiship.framework.docs.biz.pojo.dto.OptionRecycleBinDto;
import cn.chiship.framework.docs.biz.pojo.vo.FileResourcesVo;
import cn.chiship.framework.docs.biz.service.FileCatalogConfigService;
import cn.chiship.framework.docs.biz.service.FileChangeStatusService;
import cn.chiship.framework.docs.biz.service.FileResourcesService;
import cn.chiship.framework.docs.core.properties.FileUploadProperties;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.annotation.Authorization;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.encryption.Md5Util;
import cn.chiship.sdk.core.enums.HeaderEnum;
import cn.chiship.sdk.core.util.ObjectUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.framework.base.BaseController;
import cn.chiship.sdk.framework.base.BaseService;
import cn.chiship.sdk.framework.pojo.vo.PageVo;
import cn.chiship.sdk.framework.pojo.vo.UploadVo;
import cn.chiship.sdk.framework.util.ServletUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

/**
 * controller
 *
 * @author lijian
 * @date 2020/4/24
 */
@RestController
@Authorization
@RequestMapping("/fileResources")
@Api(tags = "文件资源")
public class FileResourcesController extends BaseController<FileResources, FileResourcesExample> {

	private static final Logger LOGGER = LoggerFactory.getLogger(FileResourcesController.class);

	@Resource
	private FileResourcesService fileResourcesService;

	@Resource
	private FileCatalogConfigService fileCatalogConfigService;

	@Resource
	private FileUploadProperties fileUploadProperties;

	@Resource
	private FileChangeStatusService fileChangeStatusService;

	@Override
	public BaseService getService() {
		return fileResourcesService;
	}

	@ApiOperation(value = "获取文件存储方式")
	@GetMapping(value = "/storageLocation")
	public ResponseEntity<BaseResult> storageLocation() {
		return super.responseEntity(BaseResult.ok(fileUploadProperties.getStorageLocation()));
	}

	@ApiOperation(value = "文件资源分页")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "page", value = "当前页码", defaultValue = "1", dataTypeClass = Long.class,
					paramType = "query"),
			@ApiImplicitParam(name = "limit", value = "每页条数", defaultValue = "10", dataTypeClass = Long.class,
					paramType = "query"),
			@ApiImplicitParam(name = "sort", value = "排序方式", defaultValue = "-gmtModified",
					dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "keyword", value = "关键字", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "catalogId", value = "所属文档", defaultValue = "4ca7ed82244d4eb692d91e31fabb3c9f",
					required = true, dataTypeClass = String.class, paramType = "query"), })
	@GetMapping(value = "/page")
	public ResponseEntity<BaseResult> page(
			@RequestParam(required = false, defaultValue = "1", value = "page") Long page,
			@RequestParam(required = false, defaultValue = "", value = "keyword") String keyword,
			@RequestParam(value = "catalogId") String catalogId) {
		FileResourcesExample fileResourcesExample = new FileResourcesExample();
		// 创造条件
		FileResourcesExample.Criteria criteria = fileResourcesExample.createCriteria();
		criteria.andIsDeletedEqualTo(BaseConstants.NO).andCatalogIdEqualTo(catalogId);

		FileCatalogConfigExample fileCatalogConfigExample = new FileCatalogConfigExample();

		FileCatalogConfigExample.Criteria configExampleCriteria = fileCatalogConfigExample.createCriteria();
		configExampleCriteria.andIsDeletedEqualTo(BaseConstants.NO).andCatalogPidEqualTo(catalogId);

		if (!StringUtil.isNullOrEmpty(keyword)) {
			criteria.andOriginalFileNameLike(keyword + "%");
			configExampleCriteria.andCatalogNameLike(keyword + "%");
		}

		fileCatalogConfigExample.setOrderByClause("orders asc,is_built_in desc,gmt_modified desc");

		PageVo pageVo = page(fileResourcesExample);
		List<FileResources> fileResources = pageVo.getRecords();
		List<FileResourcesVo> fileResourcesVos = new ArrayList<>();
		if (page == 1L) {
			List<FileCatalogConfig> catalogConfigs = fileCatalogConfigService.selectByExample(fileCatalogConfigExample);
			catalogConfigs.forEach(item -> {
				FileResourcesVo resourcesVo = new FileResourcesVo();
				resourcesVo.setId(item.getId());
				resourcesVo.setGmtCreated(item.getGmtCreated());
				resourcesVo.setGmtModified(item.getGmtModified());
				resourcesVo.setUuid(item.getCatalogUuid());
				resourcesVo.setName(item.getCatalogName());
				resourcesVo.setFile(false);
				resourcesVo.setRealName(item.getRealName());
				resourcesVo.setFileType(Byte.valueOf((item.getCatalogType() * -1) + ""));
				fileResourcesVos.add(resourcesVo);
			});
		}
		fileResources.forEach(item -> {
			FileResourcesVo resourcesVo = new FileResourcesVo();
			resourcesVo.setId(item.getId());
			resourcesVo.setGmtCreated(item.getGmtCreated());
			resourcesVo.setGmtModified(item.getGmtModified());
			resourcesVo.setUuid(item.getFileUuid());
			resourcesVo.setName(item.getOriginalFileName());
			resourcesVo.setFile(true);
			resourcesVo.setRealName(item.getRealName());
			resourcesVo.setFileSize(item.getFileSize());
			resourcesVo.setFileType(item.getFileType());
			resourcesVo.setFileExt(item.getFileExt());
			resourcesVo.setCatalogId(item.getCatalogId());
			resourcesVo.setStorageLocation(item.getStorageLocation());
			fileResourcesVos.add(resourcesVo);
		});
		pageVo.setRecords(fileResourcesVos);
		return super.responseEntity(BaseResult.ok(pageVo));
	}

	@ApiOperation(value = "根据文件夹获取当前用户上传文件分页")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "page", value = "当前页码", defaultValue = "1", dataTypeClass = Long.class,
					paramType = "query"),
			@ApiImplicitParam(name = "limit", value = "每页条数", defaultValue = "10", dataTypeClass = Long.class,
					paramType = "query"),
			@ApiImplicitParam(name = "sort", value = "排序方式", defaultValue = "-gmtModified",
					dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "keyword", value = "关键字", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "catalogId", value = "文件夹主键", dataTypeClass = String.class, paramType = "query",
					required = true),
			@ApiImplicitParam(name = "fileType", value = "文件类型", dataTypeClass = String.class, paramType = "query",
					required = true)

	})
	@GetMapping(value = "/user/page")
	public ResponseEntity<BaseResult> currentUserPage(@RequestParam(required = false, value = "keyword") String keyword,
			@RequestParam(required = false, value = "catalogId") String catalogId,
			@RequestParam(required = false, value = "fileType") String fileType) {
		FileResourcesExample fileResourcesExample = new FileResourcesExample();
		FileResourcesExample.Criteria criteria = fileResourcesExample.createCriteria()
				.andIsDeletedEqualTo(BaseConstants.NO).andUserIdEqualTo(getUserId());
		if (!StringUtil.isNullOrEmpty(catalogId)) {
			criteria.andCatalogIdEqualTo(catalogId);
		}
		if (!StringUtil.isNullOrEmpty(keyword)) {
			criteria.andOriginalFileNameLike(keyword + "%");
		}
		if (!StringUtil.isNullOrEmpty(fileType)) {
			List<Byte> result = new ArrayList<>();
			String[] v = fileType.split(",");
			for (String s : v) {
				result.add(Byte.valueOf(s));
			}
			criteria.andFileTypeIn(result);
		}
		PageVo pageVo = super.page(fileResourcesExample);
		List<FileResources> fileResources = pageVo.getRecords();
		/**
		 * 全部转换成UploadVo，目的是前端选择器选择与上传返回结果保持一致，减少前端因为结构不一致而单独处理
		 */
		List<UploadVo> uploadVos = new ArrayList<>();
		fileResources.forEach(file -> {
			UploadVo uploadVo = new UploadVo(file.getId(), file.getOriginalFileName(), file.getFileUuid(),
					file.getFileSize(), file.getFileType(), file.getFileExt(), file.getStorageRelativePath(),
					file.getRealName(), file.getGmtCreated());
			uploadVos.add(uploadVo);
		});
		pageVo.setRecords(uploadVos);
		return super.responseEntity(BaseResult.ok(pageVo));
	}

	@ApiOperation(value = "根据文件主键获取操作记录")
	@ApiImplicitParams({ @ApiImplicitParam(name = "fileId", value = "文件主键", dataTypeClass = String.class,
			paramType = "query", required = true) })
	@GetMapping(value = "/listChangeByFileId")
	public ResponseEntity<BaseResult> listChangeByFileId(@RequestParam(value = "fileId") String fileId) {
		FileChangeStatusExample fileChangeStatusExample = new FileChangeStatusExample();
		fileChangeStatusExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andOriginalIdEqualTo(fileId);
		fileChangeStatusExample.setOrderByClause("gmt_created desc");
		return super.responseEntity(BaseResult.ok(fileChangeStatusService.selectByExample(fileChangeStatusExample)));
	}

	@ApiOperation(value = "根据UUID获取文件详情")
	@ApiImplicitParams({ @ApiImplicitParam(name = "uuid", value = "文件标识", dataTypeClass = String.class,
			paramType = "path", required = true) })
	@GetMapping(value = "/getByUUID/{uuid}")
	public ResponseEntity<BaseResult> getByUuid(@PathVariable(value = "uuid") String uuid) {
		FileResources fileResources = fileResourcesService.cacheByFileUuid(uuid);
		return super.responseEntity(ObjectUtil.isEmpty(fileResources) ? BaseResult.ok() : BaseResult.ok(fileResources));
	}

	@ApiOperation(value = "根据UUID获取文件列表")
	@ApiImplicitParams({ @ApiImplicitParam(name = "uuids", value = "文件标识", dataTypeClass = String.class,
			paramType = "query", required = true) })
	@GetMapping(value = "/listByUUID")
	public ResponseEntity<BaseResult> listByUuid(@RequestParam(value = "uuids") String uuids) {
		List<FileResources> fileResources = fileResourcesService
				.cacheByFileUuid(StringUtil.strToListString(uuids, ","));
		return super.responseEntity(BaseResult.ok(fileResources));
	}

	@ApiOperation(value = "根据UUID获取同文件夹所有图片")
	@ApiImplicitParams({ @ApiImplicitParam(name = "uuid", value = "文件标识", dataTypeClass = String.class,
			paramType = "query", required = true) })
	@GetMapping(value = "/listSameFolderFileByUUID")
	public ResponseEntity<BaseResult> listSameFolderFileByUuid(@RequestParam(value = "uuid") String uuid) {
		return super.responseEntity(fileResourcesService.listSameFolderFileByUuid(uuid));
	}

	@ApiOperation(value = "添加收藏")
	@PostMapping(value = "/collectionAdd")
	public ResponseEntity<BaseResult> collectionAdd(@RequestBody @Valid String fileId) {
		CacheUserVO userVO = getLoginUser();
		return super.responseEntity(
				fileResourcesService.collectionAdd(ServletUtil.getHeader(HeaderEnum.HEADER_APP_ID.getName()), fileId,
						userVO.getId(), userVO.getUsername(), userVO.getRealName()));
	}

	@ApiOperation(value = "取消收藏")
	@PostMapping(value = "/collectionCancel")
	public ResponseEntity<BaseResult> collectionCancel(@RequestBody @Valid String fileId) {
		CacheUserVO userVO = getLoginUser();
		return super.responseEntity(fileResourcesService.collectionCancel(fileId, userVO.getId(), userVO.getUsername(),
				userVO.getRealName()));
	}

	@ApiOperation(value = "文件重命名")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", dataTypeClass = String.class, paramType = "path",
			required = true) })
	@PostMapping(value = "rename/{id}")
	public ResponseEntity<BaseResult> rename(@PathVariable("id") String id,
			@RequestBody @Valid FileResourcesRenameDto fileResourcesDto) {
		CacheUserVO userVO = getLoginUser();
		FileResources fileResources = new FileResources();
		BeanUtils.copyProperties(fileResourcesDto, fileResources);
		fileResources.setId(id);
		return super.responseEntity(
				fileResourcesService.rename(fileResources, userVO.getId(), userVO.getUsername(), userVO.getRealName()),
				HttpStatus.OK);
	}

	@SystemOptionAnnotation(describe = "回收站文件还原")
	@ApiOperation(value = "回收站文件还原")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", dataTypeClass = String.class, paramType = "path",
			required = true) })
	@PostMapping(value = "reduction/{id}")
	public ResponseEntity<BaseResult> reduction(@PathVariable("id") String id) {
		return super.responseEntity(fileResourcesService.reduction(id, getLoginUser().getId().toString(),
				getLoginUser().getUsername(), getLoginUser().getRealName()), HttpStatus.OK);
	}

	@ApiOperation(value = "移入回收站")
	@PostMapping(value = "/moveToRecycleBin")
	public ResponseEntity<BaseResult> moveToRecycleBin(@RequestBody @Valid OptionRecycleBinDto optionRecycleBinDto) {
		CacheUserVO userVO = getLoginUser();
		return super.responseEntity(fileResourcesService.moveToRecycleBin(
				ServletUtil.getHeader(HeaderEnum.HEADER_APP_ID.getName()), optionRecycleBinDto.getFileId(),
				optionRecycleBinDto.getType(), userVO.getId(), userVO.getUsername(), userVO.getRealName()));
	}

	/**
	 * 上传组件 自带删除按钮用
	 */
	@ApiOperation(value = "删除文件")
	@PostMapping(value = "/removeFile")
	public ResponseEntity<BaseResult> removeFile(@RequestBody @Valid String fileUuid) {
		FileResourcesExample fileResourcesExample = new FileResourcesExample();
		fileResourcesExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andFileUuidEqualTo(fileUuid);
		BaseResult baseResult = fileResourcesService.removeFile(fileUuid);
		return super.responseEntity(baseResult);
	}

	@ApiOperation(value = "清空回收站")
	@PostMapping(value = "/clearRecycleBin")
	public ResponseEntity<BaseResult> clearRecycleBin(@RequestBody @Valid OptionRecycleBinDto optionRecycleBinDto) {
		CacheUserVO userVO = getLoginUser();
		FileResourcesExample fileResourcesExample = new FileResourcesExample();
		FileResourcesExample.Criteria criteria = fileResourcesExample.createCriteria().andUserIdEqualTo(userVO.getId());
		if (optionRecycleBinDto.getIsFile() == 1) {
			criteria.andIdEqualTo(optionRecycleBinDto.getFileId());
		}
		else {
			criteria.andCatalogIdEqualTo(optionRecycleBinDto.getFileId());
		}

		return super.responseEntity(fileResourcesService.deleteByExample(fileResourcesExample));
	}

	@SystemOptionAnnotation(describe = "文件允许删除&不允许删除", option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE)
	@ApiOperation(value = "文件允许删除&不允许删除")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", dataTypeClass = String.class, paramType = "path",
			required = true) })
	@PostMapping(value = "changeIsAllowDelete/{id}")
	public ResponseEntity<BaseResult> changeIsAllowDelete(@PathVariable("id") String id,
			@RequestBody Boolean isAllowDelete) {
		CacheUserVO userVO = getLoginUser();
		return super.responseEntity(fileResourcesService.changeIsAllowDelete(isAllowDelete, id, userVO.getId(),
				userVO.getUsername(), userVO.getRealName()));
	}

	@SystemOptionAnnotation(describe = "验证文件密码")
	@ApiOperation(value = "验证文件密码")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", dataTypeClass = String.class, paramType = "path",
			required = true) })
	@PostMapping(value = "checkPassword/{id}")
	public ResponseEntity<BaseResult> checkPassword(@PathVariable("id") String id, @RequestBody String password) {

		FileResources fileResources = fileResourcesService.selectByPrimaryKey(id);

		FileResourcesExample fileResourcesExample = new FileResourcesExample();
		fileResourcesExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO).andIdEqualTo(id)
				.andEncryptionPasswordEqualTo(Md5Util.md5(password + fileResources.getEncryptionSalt()));

		List<FileResources> fileResourcesList = fileResourcesService.selectByExample(fileResourcesExample);
		if (fileResourcesList.isEmpty()) {
			return super.responseEntity(BaseResult.error("密码错误"));
		}
		return super.responseEntity(BaseResult.ok(true));
	}

}
